using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Timing;
using Volo.Abp.Caching;
using Matrix.Notification.Domain.Notifications;
using Matrix.Notification.Channels;

namespace Matrix.Notification.Services
{
    /// <summary>
    /// 默认通知路由服务实现
    /// </summary>
    public class DefaultNotificationRoutingService : INotificationRoutingService, ITransientDependency
    {
        private readonly ILogger<DefaultNotificationRoutingService> _logger;
        private readonly IClock _clock;
        private readonly IDistributedCache _cache;
        private readonly NotificationRoutingOptions _options;
        private readonly IEnumerable<INotificationChannel> _channels;

        public DefaultNotificationRoutingService(
            ILogger<DefaultNotificationRoutingService> logger,
            IClock clock,
            IDistributedCache cache,
            IOptions<NotificationRoutingOptions> options,
            IEnumerable<INotificationChannel> channels)
        {
            _logger = logger;
            _clock = clock;
            _cache = cache;
            _options = options.Value;
            _channels = channels;
        }

        public async Task<List<NotificationChannel>> GetOptimalChannelsAsync(
            NotificationMessage message,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogDebug("开始计算最优通知渠道: Type={Type}, Priority={Priority}",
                    message.Type, message.Priority);

                // 获取所有可用渠道
                var availableChannels = await GetAvailableChannelsAsync(cancellationToken);

                if (!availableChannels.Any())
                {
                    _logger.LogWarning("没有可用的通知渠道");
                    return new List<NotificationChannel>();
                }

                // 根据消息类型过滤渠道
                var candidateChannels = FilterChannelsByType(availableChannels, message.Type);

                if (!candidateChannels.Any())
                {
                    _logger.LogWarning("没有支持该类型的通知渠道: Type={Type}", message.Type);
                    return availableChannels.Take(1).ToList(); // 降级到第一个可用渠道
                }

                // 根据优先级选择渠道
                var selectedChannels = SelectChannelsByPriority(candidateChannels, message.Priority);

                _logger.LogDebug("选择的通知渠道: {Channels}", string.Join(",", selectedChannels));

                return selectedChannels;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "计算最优通知渠道失败");
                return new List<NotificationChannel>();
            }
        }

        public async Task<List<NotificationChannel>> GetOptimalChannelsForBatchAsync(
            List<NotificationMessage> messages,
            CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogDebug("开始计算批量通知最优渠道: MessageCount={Count}", messages.Count);

                // 分析消息类型分布
                var typeDistribution = messages.GroupBy(m => m.Type)
                    .ToDictionary(g => g.Key, g => g.Count());

                var channelScores = new Dictionary<NotificationChannel, double>();

                // 获取所有可用渠道
                var availableChannels = await GetAvailableChannelsAsync(cancellationToken);

                foreach (var channel in availableChannels)
                {
                    var score = await CalculateChannelScoreForBatchAsync(channel, typeDistribution, cancellationToken);
                    channelScores[channel] = score;
                }

                // 选择得分最高的渠道
                var selectedChannels = channelScores
                    .OrderByDescending(kvp => kvp.Value)
                    .Take(_options.MaxChannelsPerBatch)
                    .Select(kvp => kvp.Key)
                    .ToList();

                _logger.LogDebug("批量通知选择的渠道: {Channels}", string.Join(",", selectedChannels));

                return selectedChannels;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "计算批量通知最优渠道失败");
                return new List<NotificationChannel>();
            }
        }

        #region 私有方法

        private async Task<List<NotificationChannel>> GetAvailableChannelsAsync(CancellationToken cancellationToken)
        {
            var cacheKey = "available_notification_channels";
            var cached = await _cache.GetStringAsync(cacheKey, cancellationToken);

            if (!string.IsNullOrEmpty(cached))
            {
                return System.Text.Json.JsonSerializer.Deserialize<List<NotificationChannel>>(cached)!;
            }

            var availableChannels = new List<NotificationChannel>();

            foreach (var channel in _channels)
            {
                try
                {
                    var isAvailable = await channel.IsAvailableAsync(cancellationToken);
                    if (isAvailable)
                    {
                        if (Enum.TryParse<NotificationChannel>(channel.ChannelType, out var channelType))
                        {
                            availableChannels.Add(channelType);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "检查渠道可用性失败: Channel={Channel}", channel.ChannelType);
                }
            }

            // 缓存结果1分钟
            await _cache.SetStringAsync(
                cacheKey,
                System.Text.Json.JsonSerializer.Serialize(availableChannels),
                new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(1)
                },
                cancellationToken);

            return availableChannels;
        }

        private List<NotificationChannel> FilterChannelsByType(
            List<NotificationChannel> channels,
            NotificationType messageType)
        {
            var supportedChannels = _options.TypeChannelMappings.GetValueOrDefault(messageType);

            if (supportedChannels == null || !supportedChannels.Any())
            {
                // 如果没有特定映射，返回所有渠道
                return channels;
            }

            return channels.Where(ch => supportedChannels.Contains(ch)).ToList();
        }

        private List<NotificationChannel> SelectChannelsByPriority(
            List<NotificationChannel> channels,
            NotificationPriority priority)
        {
            var priorityConfig = _options.PriorityChannelMappings.GetValueOrDefault(priority);

            if (priorityConfig != null)
            {
                // 根据优先级配置选择渠道
                var selectedChannels = new List<NotificationChannel>();

                // 首选渠道
                foreach (var channel in priorityConfig.PrimaryChannels)
                {
                    if (channels.Contains(channel))
                    {
                        selectedChannels.Add(channel);
                    }
                }

                // 备选渠道
                if (selectedChannels.Count == 0 && priorityConfig.EnableFallback)
                {
                    foreach (var channel in priorityConfig.FallbackChannels)
                    {
                        if (channels.Contains(channel))
                        {
                            selectedChannels.Add(channel);
                        }
                    }
                }

                return selectedChannels.Any() ? selectedChannels : channels.Take(1).ToList();
            }

            // 默认选择：根据渠道可靠性排序
            return channels
                .OrderByDescending(ch => GetChannelReliability(ch))
                .Take(_options.DefaultChannelCount)
                .ToList();
        }

        private async Task<double> CalculateChannelScoreForBatchAsync(
            NotificationChannel channel,
            Dictionary<NotificationType, int> typeDistribution,
            CancellationToken cancellationToken)
        {
            double score = 0;
            var totalMessages = typeDistribution.Values.Sum();

            foreach (var typeCount in typeDistribution)
            {
                var messageType = typeCount.Key;
                var count = typeCount.Value;
                var weight = (double)count / totalMessages;

                // 检查渠道是否支持该类型
                var supportedChannels = _options.TypeChannelMappings.GetValueOrDefault(messageType);
                if (supportedChannels != null && supportedChannels.Contains(channel))
                {
                    // 基础分数
                    score += weight * 100;

                    // 渠道性能分数
                    score += GetChannelPerformanceScore(channel) * weight;

                    // 批量处理能力分数
                    score += GetBatchProcessingScore(channel) * weight;
                }
            }

            // 应用渠道负载因子
            var loadFactor = await GetChannelLoadFactorAsync(channel, cancellationToken);
            score *= (1.0 - loadFactor);

            return Math.Max(0, score);
        }

        private double GetChannelReliability(NotificationChannel channel)
        {
            return channel switch
            {
                NotificationChannel.Email => 0.85,
                NotificationChannel.Push => 0.75,
                NotificationChannel.WebHook => 0.90,
                NotificationChannel.SMS => 0.95,
                _ => 0.5
            };
        }

        private double GetChannelPerformanceScore(NotificationChannel channel)
        {
            // 基于延迟和吞吐量的性能评分
            return channel switch
            {
                NotificationChannel.Email => 80,   // 中等延迟，高可靠性
                NotificationChannel.Push => 90,    // 低延迟，中等可靠性
                NotificationChannel.WebHook => 85, // 中等延迟，高可控性
                NotificationChannel.SMS => 70,     // 高延迟，高可靠性
                _ => 50
            };
        }

        private double GetBatchProcessingScore(NotificationChannel channel)
        {
            // 批量处理能力评分
            return channel switch
            {
                NotificationChannel.Email => 90,    // 支持批量发送
                NotificationChannel.Push => 85,     // 支持批量推送
                NotificationChannel.WebHook => 95,  // 天然支持批量
                NotificationChannel.SMS => 60,     // 批量能力有限
                _ => 50
            };
        }

        private async Task<double> GetChannelLoadFactorAsync(NotificationChannel channel, CancellationToken cancellationToken)
        {
            try
            {
                var cacheKey = $"channel_load_factor:{channel}";
                var cached = await _cache.GetStringAsync(cacheKey, cancellationToken);

                if (!string.IsNullOrEmpty(cached))
                {
                    return double.Parse(cached);
                }

                // 这里应该实现实际的负载统计逻辑
                // 暂时返回随机负载因子用于演示
                var random = new Random();
                var loadFactor = random.NextDouble() * 0.3; // 0-30%的负载

                await _cache.SetStringAsync(
                    cacheKey,
                    loadFactor.ToString(),
                    new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
                    },
                    cancellationToken);

                return loadFactor;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "获取渠道负载因子失败: Channel={Channel}", channel);
                return 0.1; // 默认10%负载
            }
        }

        #endregion
    }

    #region 配置模型

    /// <summary>
    /// 通知路由选项
    /// </summary>
    public class NotificationRoutingOptions
    {
        /// <summary>
        /// 类型到渠道的映射
        /// </summary>
        public Dictionary<NotificationType, List<NotificationChannel>> TypeChannelMappings { get; set; } = new()
        {
            [NotificationType.System] = new List<NotificationChannel> { NotificationChannel.Email, NotificationChannel.Push },
            [NotificationType.Marketing] = new List<NotificationChannel> { NotificationChannel.Email, NotificationChannel.SMS },
            [NotificationType.Security] = new List<NotificationChannel> { NotificationChannel.Email, NotificationChannel.SMS, NotificationChannel.Push },
            [NotificationType.Reminder] = new List<NotificationChannel> { NotificationChannel.Email, NotificationChannel.Push }
        };

        /// <summary>
        /// 优先级到渠道的映射
        /// </summary>
        public Dictionary<NotificationPriority, PriorityChannelConfig> PriorityChannelMappings { get; set; } = new()
        {
            [NotificationPriority.Low] = new PriorityChannelConfig
            {
                PrimaryChannels = new List<NotificationChannel> { NotificationChannel.Email },
                FallbackChannels = new List<NotificationChannel> { NotificationChannel.Push },
                EnableFallback = true
            },
            [NotificationPriority.Normal] = new PriorityChannelConfig
            {
                PrimaryChannels = new List<NotificationChannel> { NotificationChannel.Email, NotificationChannel.Push },
                FallbackChannels = new List<NotificationChannel> { NotificationChannel.WebHook },
                EnableFallback = true
            },
            [NotificationPriority.High] = new PriorityChannelConfig
            {
                PrimaryChannels = new List<NotificationChannel> { NotificationChannel.Push, NotificationChannel.SMS },
                FallbackChannels = new List<NotificationChannel> { NotificationChannel.Email },
                EnableFallback = true
            },
            [NotificationPriority.Critical] = new PriorityChannelConfig
            {
                PrimaryChannels = new List<NotificationChannel> { NotificationChannel.SMS, NotificationChannel.Push, NotificationChannel.Email },
                FallbackChannels = new List<NotificationChannel> { NotificationChannel.WebHook },
                EnableFallback = true
            }
        };

        /// <summary>
        /// 默认选择的渠道数量
        /// </summary>
        public int DefaultChannelCount { get; set; } = 2;

        /// <summary>
        /// 批量发送最大渠道数
        /// </summary>
        public int MaxChannelsPerBatch { get; set; } = 3;

        /// <summary>
        /// 启用负载均衡
        /// </summary>
        public bool EnableLoadBalancing { get; set; } = true;

        /// <summary>
        /// 启用故障转移
        /// </summary>
        public bool EnableFailover { get; set; } = true;
    }

    /// <summary>
    /// 优先级渠道配置
    /// </summary>
    public class PriorityChannelConfig
    {
        /// <summary>
        /// 首选渠道列表
        /// </summary>
        public List<NotificationChannel> PrimaryChannels { get; set; } = new();

        /// <summary>
        /// 备选渠道列表
        /// </summary>
        public List<NotificationChannel> FallbackChannels { get; set; } = new();

        /// <summary>
        /// 是否启用故障转移
        /// </summary>
        public bool EnableFallback { get; set; } = true;

        /// <summary>
        /// 重试次数
        /// </summary>
        public int RetryCount { get; set; } = 3;

        /// <summary>
        /// 超时时间（秒）
        /// </summary>
        public int TimeoutSeconds { get; set; } = 30;
    }

    #endregion
}